package com.baishui.gateway.service;

import com.baishui.gateway.classloader.GateWayClassLoader;
import com.baishui.gateway.exception.GateWayException;
import com.baishui.gateway.mapper.BackInterfaceMapper;
import com.baishui.gateway.mapper.FrontBackMapper;
import com.baishui.gateway.mapper.FrontInterfaceMapper;
import com.baishui.gateway.mapper.JarMapper;
import com.baishui.gateway.utils.JarHelper;
import com.baishui.gateway.utils.StringUtilsExt;
import com.baishui.gateway.vo.FrontBackVo;
import com.baishui.gateway.vo.JarVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.jar.JarInputStream;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;

@Component
public class GatewayServiceManage {
    private final static Logger log = LoggerFactory.getLogger(GatewayServiceManage.class);

    @Autowired
    private JarMapper jarMapper;

    @Autowired
    private FrontInterfaceMapper frontInterfaceMapper;

    @Autowired
    private FrontBackMapper frontBackMapper;

    @Autowired
    private BackInterfaceMapper backInterfaceMapper;

    public void init() throws GateWayException {
        initClassLoader();
    }

    private Map<Integer, FrontBackVo> initFrontBack() throws GateWayException {
        try {
            return frontBackMapper.selectList(null).stream()
                    .collect(Collectors.toMap(FrontBackVo::getFrontId, Function.identity()));
        } catch (Exception exception) {
            log.error("initFrontBack error", exception);
        }
        return null;
    }

    private void initFrontInterface() throws GateWayException {
        try {
            Map<Integer, FrontBackVo> integerFrontBackVoMap = initFrontBack();
            if (integerFrontBackVoMap.isEmpty()) {
                log.error("front back is null,pls check");
            }
            frontInterfaceMapper.selectList(null);
        } catch (Exception exception) {
            log.error("initFrontInterface error", exception);
        }
    }


    private void initClassLoader() throws GateWayException {
        List<JarVo> jarVos = jarMapper.selectList(null);
        jarVos.forEach(jar -> {
            byte[] content = jar.getContent();
            if (Objects.nonNull(content)) {
                try (JarInputStream jarInputStream =
                             new JarInputStream(new ByteArrayInputStream(content));
                     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
                    ZipEntry nextEntry = null;
                    while ((nextEntry = jarInputStream.getNextEntry()) != null) {
                        if (nextEntry.getName().endsWith(".class")) {
                            JarHelper.toBytes(jarInputStream, byteArrayOutputStream);
                            byte[] bytes = byteArrayOutputStream.toByteArray();
                            GateWayClassLoader.getInstance().
                                    initClassLoader(StringUtilsExt.replaceClassName(nextEntry.getName())
                                            , bytes);
                        }
                    }
                } catch (IOException e) {
                    log.error("init classLoader error", e);
                }
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("init classLoader error, systemName is {}, but content is null,pls " +
                            "check! );", jar.getSystemName());
                }
            }
        });
    }

}
